package l2ft.gameserver.model.entity.events.fightclubmanager;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

import l2ft.commons.collections.MultiValueSet;
import l2ft.gameserver.ThreadPoolManager;
import l2ft.gameserver.data.xml.holder.EventHolder;
import l2ft.gameserver.data.xml.holder.FightClubMapHolder;
import l2ft.gameserver.handler.bbs.CommunityBoardManager;
import l2ft.gameserver.listener.actor.player.OnAnswerListener;
import l2ft.gameserver.model.Player;
import l2ft.gameserver.model.base.ClassId;
import l2ft.gameserver.model.entity.events.EventType;
import l2ft.gameserver.model.entity.events.GlobalEvent;
import l2ft.gameserver.model.entity.events.fightclubmanager.FightClubGameRoom.FightClubRoomTeam;
import l2ft.gameserver.model.entity.events.impl.AbstractFightClub;
import l2ft.gameserver.model.entity.events.impl.DuelEvent;
import l2ft.gameserver.model.entity.events.impl.AbstractFightClub.EVENT_STATE;
import l2ft.gameserver.model.entity.league.League;
import l2ft.gameserver.model.entity.olympiad.Olympiad;
import l2ft.gameserver.model.instances.BufferInstance;
import l2ft.gameserver.network.l2.components.ChatType;
import l2ft.gameserver.network.l2.components.SystemMsg;
import l2ft.gameserver.network.l2.s2c.ConfirmDlg;
import l2ft.gameserver.network.l2.s2c.Say2;
import l2ft.gameserver.network.l2.s2c.TutorialCloseHtml;
import l2ft.gameserver.network.l2.s2c.TutorialShowHtml;
import l2ft.gameserver.network.l2.s2c.TutorialShowQuestionMark;
import l2ft.gameserver.utils.Location;
import l2ft.gameserver.utils.Util;

public class FightClubEventManager
{
	
	public enum CLASSES {
		FIGHTERS(13113, ClassId.duelist, ClassId.dreadnought, ClassId.titan, ClassId.grandKhauatari, ClassId.maestro, ClassId.doombringer, ClassId.maleSoulhound, ClassId.femaleSoulhound),
		TANKS(13112, ClassId.phoenixKnight, ClassId.hellKnight, ClassId.evaTemplar, ClassId.shillienTemplar, ClassId.trickster),
		ARCHERS(13114, ClassId.sagittarius, ClassId.moonlightSentinel, ClassId.ghostSentinel, ClassId.fortuneSeeker),
		DAGGERS(13114, ClassId.adventurer, ClassId.windRider, ClassId.ghostHunter, ClassId.dominator),
		MAGES(13116, ClassId.archmage, ClassId.soultaker, ClassId.mysticMuse, ClassId.stormScreamer),
		SUMMONERS(13118, ClassId.arcanaLord, ClassId.elementalMaster, ClassId.spectralMaster),
		HEALERS(13115, ClassId.cardinal, ClassId.evaSaint, ClassId.shillienSaint),
		SUPPORTS(13117, ClassId.hierophant, ClassId.swordMuse, ClassId.spectralDancer, ClassId.doomcryer, ClassId.judicator);
		
		private int _transformId;
		private ClassId[] _classes;
		private CLASSES(int transformId, ClassId... ids)
		{
			_transformId = transformId;
			_classes = ids;
		}
		
		public ClassId[] getClasses()
		{
			return _classes;
		}
		
		public int getTransformId()
		{
			return _transformId;
		}
	}
	
	private static FightClubEventManager _instance;
	public static final String BYPASS = "_fightclub";
	
	public static final Location RETURN_LOC = new Location(83208, 147672, -3494, 0);
	public static final int FIGHT_CLUB_BADGE_ID = 57;//TODO
	
	private Map<Integer, AbstractFightClub> _activeEvents = new ConcurrentHashMap<>();
	private List<FightClubGameRoom> _rooms = new CopyOnWriteArrayList<>();
	private boolean _shutDown = false;
	private boolean _creatingRoomsBlocked = false;
	
	public void serverShutDown(int seconds)
	{
		_shutDown = true;
		ThreadPoolManager.getInstance().schedule(new Runnable() {
			
			@Override
			public void run()
			{
				//Check if it wasnt aborted
				if(_shutDown)
					for(FightClubGameRoom room : getAllRooms())
						room.blockJoiningRoom(true);
			}
		}, Math.max(0, (seconds-150)*1000));
	}
	
	public void stopShutDown()
	{
		_shutDown = false;
		
		for(FightClubGameRoom room : getAllRooms())
			room.blockJoiningRoom(false);
	}
	
	public boolean serverShuttingDown()
	{
		return _shutDown;
	}
	
	/*
	 * 
	 * Player
	 * 
	 */

	public void signForQuickBattle(Player player)
	{
		System.out.println("checking if can participate");
		if(!canPlayerParticipate(player, true, null, false))
			return;
		
		if(checkQuickBattle(player))
			return;//Success
		
		sendErrorMessageToPlayer(player, "There are no games You could take part in!");
	}
	
	private boolean checkQuickBattle(Player player)
	{
		int bestRoomPoints = -1;
		FightClubGameRoom bestRoom = null;
		
		for(FightClubGameRoom room : getAllRooms())
		{
			if(!canPlayerParticipate(player, false, room, true))
				continue;
			
			int points = (room.getGame() == null ? 0 : 10);
			points += room.getAllPlayers().size();
			
			//Points for odd Healers count
			if(room.isTeamed() && player.getClassId() == ClassId.cardinal && oddHealersCount(room))
				points += 10;
			System.out.println("points:"+points);
			if(bestRoomPoints < points)
			{
				bestRoomPoints = points;
				bestRoom = room;
			}
		}
		System.out.println("best room:"+bestRoom);
		if(bestRoom != null)
		{
			addNewPlayerToEvent(player, bestRoom);
			return true;
		}
		return false;
	}
	
	private boolean oddHealersCount(FightClubGameRoom room)
	{
		int healers = 0;
		for(Player iPlayer : room.getAllPlayers())
		{
			if(iPlayer.getClassId() == ClassId.cardinal)
				healers++;
		}
		return healers % 2 == 1;
	}
	
	public boolean addNewPlayerToEvent(Player player, FightClubGameRoom room)
	{
		AbstractFightClub activeEvent = room.getGame();
		
		if(room.getSlotsLeft() <= 0 || room.isJoiningBlocked())
		{
			sendErrorMessageToPlayer(player, "No enough slots!");
			return false;
		}
		
		if(activeEvent != null && !activeEvent.canAddNewPlayer(player))
		{
			sendErrorMessageToPlayer(player, "Event is closed!");
			return false;
		}
		
		if(player.isRegisteredInFightClub() || player.getFightClubGameRoom() != null)
		{
			sendErrorMessageToPlayer(player, "You are already registered to Fight Club!");
			return false;
		}
		
		if(room.getGame() != null)
		{
			if(!canPlayerParticipate(player, true, room, false))
				return false;
			
			room.addAlonePlayer(player);
			
			activeEvent.addNewPlayer(player);
		}
		else
		{
			if(!canPlayerParticipate(player, true, room, true))
				return false;
			
			room.addAlonePlayer(player);
		}
		
		return true;
	}
	
	public void playerLoggedIn(Player player)
	{
		for(AbstractFightClub event : _activeEvents.values())
			event.loggedIn(player);
	}
	
	public boolean canEventStart(Player creator, FightClubGameRoom room)
	{
		if(!canPlayerParticipate(creator, true, room, false))
			return false;
		
		if(room.getSlotsLeft() < 0)
		{
			sendErrorMessageToPlayer(creator, "There are too many players registered!");
			return false;
		}
		
		if(room.isStartingEventBlocked())
		{
			sendErrorMessageToPlayer(creator, "Starting event is currently blocked!");
			return false;
		}
		
		if(room.isTeamed())
		{
			int playersInTeams = -1;
			for(FightClubRoomTeam team : room.getTeams())
			{
				if(playersInTeams == -1)
					playersInTeams = team.getMembersCount();
				else if(team.getMembersCount() != playersInTeams)
				{
					sendErrorMessageToPlayer(creator, "Every Team needs to have same amount of players!");
					return false;
				}
			}
		}
		
		return true;
	}
	
	/**
	 * room can be null
	 */
	public boolean canPlayerParticipate(Player player, boolean sendMessage, FightClubGameRoom room, boolean justMostImportant)
	{
		if(player == null)
			return false;
		
		if(room != null)
		{
			if(room.getMinLeague().ordinal() < player.getLeague().ordinal())
			{
				if(sendMessage)
					sendErrorMessageToPlayer(player, "Your League is too low to join that Room!");
				return false;
			}
			
			if(room.getMaxLeague().ordinal() > player.getLeague().ordinal())
			{
				if(sendMessage)
					sendErrorMessageToPlayer(player, "Your League is too high to join that Room!");
				return false;
			}
			
			AbstractFightClub event = room.getGameForType();

			if(!isClassFreeToJoin(player.getClassId(), event))
			{
				if(sendMessage)
					sendErrorMessageToPlayer(player, "Your class cannot take part in "+event.getName()+"!");
				return false;
			}
		}

		if(player.getClassId().level() != 3)
		{
			sendErrorMessageToPlayer(player, "Your class is too weak for the Fight Club!");
			return false;
		}
		
		if(player.getCursedWeaponEquippedId() > 0)
		{
			if(sendMessage)
				sendErrorMessageToPlayer(player, "Cursed Weapon owners may not participate in Fight Club!");
			return false;
		}
		
		if(Olympiad.isRegistered(player))
		{
			if(sendMessage)
				sendErrorMessageToPlayer(player, "Players registered to Olympiad Match may not participate in Fight Club!");
			return false;
		}
		
		if(player.isInOlympiadMode() || player.getOlympiadGame() != null)
		{
			if(sendMessage)
				sendErrorMessageToPlayer(player, "Players fighting in Olympiad Match may not participate in Fight Club!");
			return false;
		}
		
		if(player.isInObserverMode())
		{
			if(sendMessage)
				sendErrorMessageToPlayer(player, "Players in Observation mode may not participate in Fight Club!");
			return false;
		}
		
		if(!justMostImportant)
		{
			if(player.isDead() || player.isAlikeDead())
			{
				if(sendMessage)
					sendErrorMessageToPlayer(player, "Dead players may not participate in Fight Club!");
				return false;
			}
			
			if(!player.isInPeaceZone() && player.getPvpFlag() > 0)
			{
				if(sendMessage)
					sendErrorMessageToPlayer(player, "Players in PvP Battle may not participate in Fight Club!");
				return false;
			}
			
			if(player.isInCombat())
			{
				if(sendMessage)
					sendErrorMessageToPlayer(player, "Players in Combat may not participate in Fight Club Battle!");
				return false;
			}
			
			if(player.getEvent(DuelEvent.class) != null)
			{
				if(sendMessage)
					sendErrorMessageToPlayer(player, "Players engaged in Duel may not participate in Fight Club Battle!");
				return false;
			}
			
			if(player.getKarma() > 0)
			{
				if(sendMessage)
					sendErrorMessageToPlayer(player, "Chaotic players may not participate in Fight Club!");
				return false;
			}
			
			if(player.isInOfflineMode())
			{
				if(sendMessage)
					sendErrorMessageToPlayer(player, "Players in Offline mode may not participate in Fight Club!");
				return false;
			}
			
			if(player.isInStoreMode())
			{
				if(sendMessage)
					sendErrorMessageToPlayer(player, "Players in Store mode may not participate in Fight Club!");
				return false;
			}
		}
		
		return true;
	}

	/*
	 * 
	 * Rooms
	 * 
	 */

	public void startNewEvent(Player player, FightClubGameRoom room)
	{
		AbstractFightClub event = EventHolder.getInstance().getEvent(EventType.FIGHT_CLUB_EVENT, room.getGameType());
		String changedEventName = Util.getChangedEventName(event);
		
		if(room.getPlayersInside() < FightClubMapHolder.getInstance().getMinPlayersForEvent(changedEventName))
		{
			sendErrorMessageToPlayer(player, "There are no enough players to start the event!");
			return;
		}
		
		AbstractFightClub duplicatedEvent = prepareNewEvent(event);
		duplicatedEvent.startTeleportTimer(room);
	}

	public void removeRoom(FightClubGameRoom room)
	{
		if(room != null && _rooms.contains(room))
			_rooms.remove(room);
	}
	
	public void destroyRoom(Player player, FightClubGameRoom room)
	{
		_rooms.remove(room);
		room.destroyMe();
	}
	
	public boolean isRoomFine(Player player, int eventType, String name, League minLeague, League maxLeague)
	{
		AbstractFightClub event = (AbstractFightClub) EventHolder.getInstance().getEvent(EventType.FIGHT_CLUB_EVENT, eventType);
		
		if(!canPlayerParticipate(player, true, null, true))
			return false;
		
		if(_creatingRoomsBlocked)
		{
			sendErrorMessageToPlayer(player, "Cannot create room at this moment!");
			return false;
		}
		
		if(!isClassFreeToJoin(player.getClassId(), event))
		{
			sendErrorMessageToPlayer(player, "Your class cannot take part in "+event.getName()+"!");
			return false;
		}
		
		if(name.isEmpty() || name.length() < 3)
		{
			sendErrorMessageToPlayer(player, "Room name needs to have at least 3 characters!");
			return false;
		}
		
		if(name.length() > 15)
		{
			sendErrorMessageToPlayer(player, "Room name can't have more than 15 characters!");
			return false;
		}
		
		if(minLeague.ordinal() < maxLeague.ordinal())
		{
			sendErrorMessageToPlayer(player, "Min League can't be better than max League!");
			return false;
		}
		
		if(minLeague.ordinal() < player.getLeague().ordinal())
		{
			sendErrorMessageToPlayer(player, "Your League is too low to join that Room!");
			return false;
		}
		
		if(maxLeague.ordinal() > player.getLeague().ordinal())
		{
			sendErrorMessageToPlayer(player, "Your League is too high to join that Room!");
			return false;
		}
		
		return true;
	}
	
	public void createRoom(Player player, int eventType, String name, League minLeague, League maxLeague, int numberOfTeams)
	{
		FightClubGameRoom newRoom = new FightClubGameRoom(player, name, minLeague, maxLeague, eventType, numberOfTeams);
		_rooms.add(newRoom);
		player.sendMessage("Room has been created!");
	}

	public FightClubGameRoom getRoomById(int roomId)
	{
		for(FightClubGameRoom room : _rooms)
			if(room.getIndex() == roomId)
				return room;
		return null;
	}

	public List<FightClubGameRoom> getAllRooms()
	{
		return _rooms;
	}

	/**
	 * Try to don't use that
	 */
	public FightClubGameRoom findMyRoom(Player player)
	{
		return player.getFightClubGameRoom();
	}
	
	/*
	 * 
	 * Admin Commands
	 * 
	 */
	public void blockJoiningAllRooms(Player player)
	{
		int blockedRooms = 0;
		int unblockedRooms = 0;
		for(FightClubGameRoom room : getAllRooms())
		{
			if(room.isJoiningBlocked())
				unblockedRooms++;
			else
				blockedRooms++;
			room.blockJoiningRoom();
		}
		
		player.sendMessage("Blocked "+blockedRooms+" rooms, unblocked "+unblockedRooms+" rooms!");
	}
	
	public void blockJoiningRoom(Player admin, Player target)
	{
		FightClubGameRoom room = findMyRoom(target);
		if(room == null)
		{
			admin.sendMessage("Target doesn't have any room!");
			return;
		}
		
		room.blockJoiningRoom();
		if(room.isJoiningBlocked())
			admin.sendMessage("Joining to this room is now blocked!");
		else
			admin.sendMessage("Joining to this room is now unlocked!");
	}
	
	public void blockCreatingRooms(Player admin)
	{
		_creatingRoomsBlocked = !_creatingRoomsBlocked;
		admin.sendMessage("Creating new rooms is now "+(_creatingRoomsBlocked ? "Blocked" : "Unblocked")+"!");
	}
	
	public void blockStartingAllEvents(Player admin)
	{
		int blockedRooms = 0;
		int unblockedRooms = 0;
		for(FightClubGameRoom room : getAllRooms())
		{
			if(room.isStartingEventBlocked())
				unblockedRooms++;
			else
				blockedRooms++;
			room.blockStartingEvent();
		}
		
		admin.sendMessage("Blocked starting "+blockedRooms+" events, unblocked starting "+unblockedRooms+" events!");
	}
	
	public void blockStartingAllEvent(Player admin, Player target)
	{
		FightClubGameRoom room = findMyRoom(target);
		if(room == null)
		{
			admin.sendMessage("Target doesn't have a room");
			return;
		}
		
		room.blockStartingEvent();
		
		admin.sendMessage("Starting Event by this room is now "+room.isStartingEventBlocked()+"!");
	}
	
	public void destroyAllRooms(Player admin)
	{
		int destroyedRooms = 0;
		for(FightClubGameRoom room : getAllRooms())
		{
			destroyedRooms++;
			room.stopCountDown();
			room.destroyMe();
		}
		_rooms.clear();
		
		admin.sendMessage("Destroyed "+destroyedRooms+" rooms!");
	}
	
	public void destroyRoom(Player admin, Player target)
	{
		FightClubGameRoom room = findMyRoom(target);
		if(room == null)
		{
			admin.sendMessage("Target doesn't have a room");
			return;
		}
		room.stopCountDown();
		room.destroyMe();
		_rooms.remove(room);
		admin.sendMessage("Room has been destroyed!");
	}
	
	public void stopAllRoomsCountdowns(Player admin)
	{
		int stopped = 0;
		for(FightClubGameRoom room : getAllRooms())
		{
			if(room.getGame() != null)
			{
				stopped++;
				room.stopCountDown();
			}
		}
		
		admin.sendMessage("Stopped countdown of "+stopped+" rooms!");
	}
	
	public void stopRoomCountdown(Player admin, Player target)
	{
		FightClubGameRoom room = findMyRoom(target);
		if(room == null)
		{
			admin.sendMessage("Target doesn't have a room");
			return;
		}
		room.stopCountDown();
		admin.sendMessage("Countdown stopped!");
	}
	
	public void finishAllEvents(Player admin)
	{
		for(AbstractFightClub event : _activeEvents.values())
			event.stopEventByAdmin();
		admin.sendMessage(_activeEvents.size()+" events finished!");
		_activeEvents.clear();
	}
	
	public void finishEvent(Player admin, Player target)
	{
		AbstractFightClub club = target.getFightClubEvent();
		if(club == null)
		{
			admin.sendMessage("Target isn't in Fight Club!");
			return;
		}
		club.stopEventByAdmin();
		admin.sendMessage("Event Finished!");
	}
	
	public void kickFromEvent(Player admin, Player target)
	{
		AbstractFightClub club = target.getFightClubEvent();
		if(club == null)
		{
			admin.sendMessage("Target isn't in Fight Club!");
			return;
		}
		club.leaveEvent(target, false);
		admin.sendMessage("Player have been kicked from event!");
		target.sendMessage("You have been kicked from event by admin!");
	}
	
	public void endEventRound(Player admin, Player target)
	{
		AbstractFightClub club = target.getFightClubEvent();
		if(club == null)
		{
			admin.sendMessage("Target isn't in Fight Club!");
			return;
		}
		club.endRound();
		admin.sendMessage("Round ended!");
	}
	
	/*
	 * 
	 * Other
	 * 
	 */
	
	private void sendErrorMessageToPlayer(Player player, String msg)
	{
		player.sendPacket(new Say2(player.getObjectId(), ChatType.COMMANDCHANNEL_ALL, "Error", msg));
	}
	
	private AbstractFightClub prepareNewEvent(AbstractFightClub event)
	{
		MultiValueSet<String> set = event.getSet();
		AbstractFightClub duplicatedEvent = null;
		try
		{
			@SuppressWarnings("unchecked")
			Class<GlobalEvent> eventClass = (Class<GlobalEvent>) Class.forName(set.getString("eventClass"));
			Constructor<GlobalEvent> constructor = eventClass.getConstructor(MultiValueSet.class);
			duplicatedEvent = (AbstractFightClub) constructor.newInstance(set);
			
			duplicatedEvent.clearSet();
			duplicatedEvent.setObjects(event.getObjects());
			duplicatedEvent.prepareEvent();
			_activeEvents.put(duplicatedEvent.getObjectId(), duplicatedEvent);
			
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
			e.printStackTrace();
		}
		
		return duplicatedEvent;
	}
	
	public void requestEventPlayerMenuBypass(Player player, String bypass)
	{
		player.sendPacket(TutorialCloseHtml.STATIC);
		
		//Getting event
		AbstractFightClub event = player.getFightClubEvent();
		if(event == null)
			return;
		
		//Getting fPlayer
		FightClubPlayer fPlayer = event.getFightClubPlayer(player);
		if(fPlayer == null)
			return;
		
		//Player isnt viewing main event page now
		fPlayer.setShowTutorial(false);
		
		System.out.println(bypass);
		if(bypass.startsWith("npc"))
		{
			BufferInstance.bypass(player, bypass);
			return;
		}
		//Checking if its the right bypass
		if(!bypass.startsWith(BYPASS))
			return;
		
		//Getting action
		StringTokenizer st = new StringTokenizer(bypass," ");
		st.nextToken();//_fightclub
		
		String action = st.nextToken();
		
		switch(action)
		{
		case "scheme":
			BufferInstance.showFightClubMain(player);
			break;
		case "changeEvent":
			if(event.getState() == EVENT_STATE.NOT_ACTIVE)
				changeEvent(player);
			else
				askQuestion(player, 2, "Are you sure You want to change Event?");
			break;
		case "leave":
			if(event.getState() == EVENT_STATE.NOT_ACTIVE)
				leaveEvent(player);
			else
				askQuestion(player, 1, "Are you sure You want to leave the event?");
			break;
		}
	}
	
	public void sendEventPlayerMenu(Player player)
	{
		System.out.println("sending event player meny");
		AbstractFightClub event = player.getFightClubEvent();
		if(event == null || event.getFightClubPlayer(player) == null)
		{
			System.out.println("passed first, reflection id:"+player.getReflectionId());
			if(player.getReflectionId() > 0)
			{
				System.out.println("showing game");
				showChooseGame(player);
				player.sendPacket(new TutorialShowQuestionMark(100));
			}
			return;
		}
		
		FightClubPlayer fPlayer = event.getFightClubPlayer(player);
		
		//Player is viewing main event page now
		fPlayer.setShowTutorial(true);
		
		System.out.println("sending tutorial");
		
		String html = "<html><head><title>"+event.getName()+"</title></head>";
		html += "<body>";
		html += "<br1><img src=\"L2UI.squaregray\" width=\"290\" height=\"1\">";
		html += "<table height=20 fixwidth=\"290\" bgcolor=29241d>";
		html += "	<tr>";
		html += "		<td height=20 width=290>";
		html += "			<center><font name=\"hs12\" color=913d3d>"+event.getName()+"</font></center>";
		html += "		</td>";
		html += "	</tr>";
		html += "</table>";
		html += "<br1><img src=\"L2UI.squaregray\" width=\"290\" height=\"1\">";
		html += "<br>";
		html += "<table fixwidth=290 bgcolor=29241d>";
		html += "	<tr>";
		html += "		<td valign=top width=280>";
		html += "			<font color=388344>"+replaceDescription(event, event.getDescription(), true)+"<br></font>";
		html += "		</td>";
		html += "	</tr>";
		html += "</table>";
		html += "<br1><img src=\"L2UI.squaregray\" width=\"290\" height=\"1\">";
		html += "<br>";
		
		if(fPlayer.getAchProgress() != null)
		{
			html += "<table fixwidth=290 bgcolor=29241d>";
			html += "	<tr>";
			html += "		<td valign=top width=290>";
			html += "			<font color=913d3d>Achievement:</font><br1>";
			html += "			<font color=9b5b2c>"+FightClubAchievements.getInstance().getChangedName(fPlayer)+"<br></font>";
			html += "		</td>";
			html += "	</tr>";
			html += "</table>";
			html += "<br1><img src=\"L2UI.squaregray\" width=\"290\" height=\"1\">";
			html += "<br>";
		}
		
		html += "<table width=270>";
		if(event.getBuffer())
		{
			html += "	<tr>";
			html += "		<td>";
			html += "			<center><button value = \"Buffer\" action=\"bypass -h "+BYPASS+" scheme\" back=\"l2ui_ct1.button.OlympiadWnd_DF_HeroConfirm_Down\" width=200 height=30 fore=\"l2ui_ct1.button.OlympiadWnd_DF_HeroConfirm\"></center>";
			html += "		</td>";
			html += "	</tr>";
		}
		html += "	<tr>";
		html += "		<td>";
		html += "			<center><button value = \"Change Event\" action=\"bypass -h "+BYPASS+" changeEvent\" back=\"l2ui_ct1.button.OlympiadWnd_DF_Fight3None_Down\" width=200 height=30 fore=\"l2ui_ct1.button.OlympiadWnd_DF_Fight3None\"></center>";
		html += "		</td>";
		html += "	</tr>";
		html += "	<tr>";
		html += "		<td>";
		html += "			<center><button value = \"Leave Event\" action=\"bypass -h "+BYPASS+" leave\" back=\"l2ui_ct1.button.OlympiadWnd_DF_Back_Down\" width=200 height=30 fore=\"l2ui_ct1.button.OlympiadWnd_DF_Back\"></center>";
		html += "		</td>";
		html += "	</tr>";
		html += "	<tr>";
		html += "		<td>";
		html += "			<center><button value = \"Close\" action=\"bypass -h "+BYPASS+" close\" back=\"l2ui_ct1.button.OlympiadWnd_DF_Info_Down\" width=200 height=30 fore=\"l2ui_ct1.button.OlympiadWnd_DF_Info\"></center>";
		html += "		</td>";
		html += "	</tr>";
		html += "</table>";
		
		html += "</body></html>";
		
		player.sendPacket(new TutorialShowHtml(html));
		player.sendPacket(new TutorialShowQuestionMark(100));
	}
	
	public String replaceDescription(AbstractFightClub eventInstance, String description, boolean showWhole)
	{
		AbstractFightClub event = EventHolder.getInstance().getEvent(EventType.FIGHT_CLUB_EVENT, eventInstance.getId());
		
		if(!showWhole)
		{
			int firstIndex = description.indexOf("<");
			if(firstIndex > 0)
				description = description.substring(0, firstIndex);
		}
		List<String> content = getContentToReplace(description, showWhole);
		for(String s : content)
		{
			System.out.println(s);
			description = description.replace(s, event.getSet().getString(s.replace("%", "")));
		}
		
		return description;
	}
	
	private List<String> getContentToReplace(String wholeText, boolean showWhole)
	{
		List<String> content = new ArrayList<>();
		char[] array = wholeText.toCharArray();
		int startI = -1;
		
		for(int i = 0;i<array.length;i++)
		{
			if(array[i] == '%')
			{
				if(startI == -1)
					startI = i;
				else
				{
					content.add(wholeText.substring(startI, i+1));
					startI = -1;
				}
			}
			else if(!showWhole)
			{
				System.out.println("!showWhole, array[i]:"+array[i]);
				if(array[i] == '<')
					return content;
			}
		}
		return content;
	}

	private void leaveEvent(Player player)
	{
		AbstractFightClub event = player.getFightClubEvent();
		if(event == null)
			return;
		
		if(event.leaveEvent(player, true))
			player.sendMessage("You have left the event!");
	}
	
	private void changeEvent(Player player)
	{
		AbstractFightClub event = player.getFightClubEvent();
		if(event == null)
			return;
		
		if(event.leaveEvent(player, false))
			showChooseGame(player);
	}
	
	private void showChooseGame(Player player)
	{
		CommunityBoardManager.getInstance().getCommunityHandler("_fightClubChooseGame_").onBypassCommand(player, "_fightClubChooseGame_");
	}
	
	private void askQuestion(Player player, int index, String question)
	{
		ConfirmDlg packet = new ConfirmDlg(SystemMsg.S1, 60000).addString(question);
		player.ask(packet, new AskQuestionAnswerListener(player, index));
	}
	
	private boolean isClassFreeToJoin(ClassId id, AbstractFightClub event)
	{
		for(CLASSES classes : event.getExcludedClasses())
			for(ClassId excludedClass : classes._classes)
				if(excludedClass.equals(id))
					return false;
		return true;
	}
	
	private class AskQuestionAnswerListener implements OnAnswerListener
	{
		private final Player _player;
		private final int _index;
		
		private AskQuestionAnswerListener(Player player, int index)
		{
			_player = player;
			_index = index;
		}
		
		@Override
		public void sayYes()
		{
			switch(_index)
			{
			case 1://Leaving event
				leaveEvent(_player);
				break;
			case 2://Switch event?
				changeEvent(_player);
				break;
			}
		}

		@Override
		public void sayNo()
		{}
		
	}
	
	public AbstractFightClub getEventByObjId(int objId)
	{
		return _activeEvents.get(objId);
	}
	
	public static FightClubEventManager getInstance()
	{
		if(_instance == null)
			_instance = new FightClubEventManager();
		return _instance;
	}
}
